<?php

namespace App\Service\Workflow;

use App\Enums\Workflow\WorkflowV2Enum;
use App\Library\FeiShu\SendFs;
use App\Models\Workflow\WorkflowV2TemplateModel;
use App\Models\Workflow\WorkflowV2TemplateNodeModel;
use App\Service\BaseService;
use App\Service\OpenShop\Feishu\MainProcessService;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Kuafu\GeneralFs\BuildFs;

class WorkflowV2TemplateService extends BaseService
{
    private int    $currentUserId;
    private string $currentUserName;

    public function __construct(int $uid, string $username)
    {
        $this->currentUserId   = $uid;
        $this->currentUserName = $username;
    }

    private WorkflowV2TemplateModel $workflowV2TemplateModel;

    public function addOrEdit(int $templateId, string $name, int $workflowType, int $workflowType2, int $sort, array $nodes): int
    {
        // 记录nodeKey => nodeId
        $nodeKeyToNodeId = [];

        DB::beginTransaction();

        // workflow_template 模板
        $this->workflowV2TemplateModel = WorkflowV2TemplateModel::query()->firstOrNew(['id' => $templateId]);
        $oldWorkflowTemplateModel      = clone $this->workflowV2TemplateModel;
        $oldWorkflowTemplateNodes      = $oldWorkflowTemplateModel->nodes;

        $this->workflowV2TemplateModel->name                   = $name;
        $this->workflowV2TemplateModel->workflowType           = $workflowType;
        $this->workflowV2TemplateModel->workflowType2          = $workflowType2;
        $this->workflowV2TemplateModel->sort                   = $sort;
        $this->workflowV2TemplateModel->submitCruiseTemplateId = $nodes['cruiseTemplateId'] ?? 0; // 第一个模板id

        if ($templateId == 0) {
            $this->workflowV2TemplateModel->templateNo = MainProcessService::generateOrderNo('SPL');
            $this->workflowV2TemplateModel->status     = WorkflowV2TemplateModel::STATUS_OFF;
        }
        $this->workflowV2TemplateModel->save();

        // 删除原有数据 - 硬删
        if ($templateId != 0) {
            $this->delete($templateId, false, false);
        }

        // 递归插入节点
        $this->recursionDecodeChildNode(0, $nodes);

        // 事后补救
        // 修复父分支下nextId=0的节点，统一更新成父节点的nextId
        // 目前默认不能以分支结构作为最后一个节点
        $lastNodeId = WorkflowV2TemplateNodeModel::query()
                                                 ->where('workflowTemplateId', $this->workflowV2TemplateModel->id)
                                                 ->where('nextId', 0)
                                                 ->orderByDesc('id')
                                                 ->value('id');

        WorkflowV2TemplateNodeModel::query()
                                   ->where('workflowTemplateId', $this->workflowV2TemplateModel->id)
                                   ->where('nextId', 0)
                                   ->where('id', '<', $lastNodeId)
                                   ->get()
                                   ->each(function (WorkflowV2TemplateNodeModel $node) {

                                       // 一直找prevId，直到找到nodeType=4的节点，取nextId
                                       $nextId = $this->findPrevIfMainNode($node->prevId);
                                       if ($nextId) {
                                           $node->nextId = $nextId;
                                           $node->save();

                                           Log::info("事后补救 - 更新节点nextId成功，nodeId:{$node->id} nextId:{$nextId}");
                                       }
                                   });

        DB::commit();

        if ($templateId) {
            $title = "编辑";
        } else {
            $title = "新增";
        }

        $oldNodesJson = json_encode($oldWorkflowTemplateNodes, JSON_UNESCAPED_UNICODE);
        $newNodesJson = json_encode($nodes, JSON_UNESCAPED_UNICODE);

        // 审计日志
        $content = vsprintf("工作审批流模板【{$title}】 \n\n  id:%s \n\n name:%s => %s \n\n workflowType:%s => %s \n\n oldNodes:%s \n\n newNodes:%s \n\n 操作人:%s-%s",
            [
                $templateId,
                $oldWorkflowTemplateModel->name ?? '',
                $name,
                $oldWorkflowTemplateModel->workflowType ?? '',
                $workflowType,
                $oldNodesJson,
                $newNodesJson,
                $this->currentUserName,
                $this->currentUserId
            ]);
        BuildFs::newRobot(SendFs::ROBOT_AUDIT_LOG)->setTitleContent("审批流v2 - 审计消息", $content)->send();

        return $this->workflowV2TemplateModel->id;
    }

    /**
     * 往前找到最近的if_main节点
     * @param int $id
     * @return int
     */
    private function findPrevIfMainNode(int $id): int
    {
        $node = WorkflowV2TemplateNodeModel::query()->where('id', $id)->first();
        if (!$node) {
            return 0;
        }

        if ($node->nodeType == WorkflowV2Enum::NODE_TYPE_IF_MAIN) {
            return $node->nextId;
        }

        return $this->findPrevIfMainNode($node->prevId);
    }

    /**
     * 上个节点的id
     * @var int
     */
    private int $prevId = 0;

    /**
     * 递归拆解childNode
     * @param array $childNode
     */
    private function recursionDecodeChildNode(int $prevId, array $childNode)
    {
        $this->prevId = $prevId;

        $nodeKey          = $childNode['nodeKey'];
        $nodeName         = $childNode['nodeName'];
        $nodeType         = $childNode['nodeType'] ?? 0;
        $handlerType      = $childNode['handlerType'] ?? 0;
        $handlerUids      = $childNode['handlerUids'] ?? [];
        $businessType     = $childNode['businessType'] ?? 0;
        $cruiseTemplateId = $childNode['cruiseTemplateId'] ?? 0;
        $conditionNodes   = $childNode['conditionNodes'] ?? [];
        $ccInfo           = $childNode['ccInfo'] ?? [];
        $childNode        = $childNode['childNode'] ?? [];

        // workflow_template_node - 主节点、父节点
        $nodeModel = WorkflowV2TemplateNodeModel::query()->create([
            'workflowTemplateId' => $this->workflowV2TemplateModel->id,
            'pId'                => 0,
            'nextId'             => 0,
            'prevId'             => $prevId,
            'businessType'       => $businessType,
            'name'               => $nodeName,
            'nodeType'           => $nodeType,
            'handlerType'        => $handlerType,
            'handlerUids'        => json_encode($handlerUids),
            'status'             => WorkflowV2TemplateModel::STATUS_ON,
            'cruiseTemplateId'   => $cruiseTemplateId,
            'ccInfo'             => json_encode($ccInfo, JSON_UNESCAPED_UNICODE),
        ]);

        // 除了最后一个节点，更新上个节点的nextId
        if ($this->prevId > 0) {
            WorkflowV2TemplateNodeModel::query()->where('id', $this->prevId)->update(['nextId' => $nodeModel->id]);

            // 如果上个节点是条件父集，把条件子集的nextId也更新一下
            $prevNode = WorkflowV2TemplateNodeModel::query()->where('id', $this->prevId)->first();

            if ($prevNode->nodeType == WorkflowV2Enum::NODE_TYPE_IF_MAIN) {

                // TODO 找分支下最深的节点 !!!!!!

//                WorkflowV2TemplateNodeModel::query()
//                                           ->where('pId', $prevNode->id)
//                                           ->get()
//                                           ->each(function ($item) use ($nodeModel) {
//                                               WorkflowV2TemplateNodeModel::query()
//                                                                          ->where('pId', 0)
//                                                                          ->where('prevId', $item->id)
//                                                                          ->update(['nextId' => $nodeModel->id]);
//                                           });
            }
        }

        // 有分支结构
        if ($conditionNodes) {
            foreach ($conditionNodes as $conditionNode) {

                $nodeKey            = $conditionNode['nodeKey'];
                $conditionNodeName  = $conditionNode['nodeName'];
                $conditionNodeType  = $conditionNode['nodeType'];
                $conditionList      = $conditionNode['conditionList'];
                $conditionChildNode = $conditionNode['childNode'] ?? [];

                $nodeConditionModel = WorkflowV2TemplateNodeModel::query()->create([
                    'workflowTemplateId' => $this->workflowV2TemplateModel->id,
                    'pId'                => $nodeModel->id,
                    'nextId'             => 0,
                    'prevId'             => $nodeModel->id,
                    'businessType'       => 0,
                    'name'               => $conditionNodeName,
                    'nodeType'           => $conditionNodeType,
                    'handlerType'        => 0,
                    'handlerUids'        => '[]',
                    'condition'          => json_encode($conditionList, JSON_UNESCAPED_UNICODE), // 条件
                    'status'             => WorkflowV2TemplateModel::STATUS_ON,
                    'cruiseTemplateId'   => 0,
                    'ccInfo'             => null,
                ]);

                // 递归condition下的childNode
                if ($conditionChildNode) {
                    $this->recursionDecodeChildNode($nodeConditionModel->id, $conditionChildNode);
                }
            }
        }

        // 继续递归
        if ($childNode) {
            return $this->recursionDecodeChildNode($nodeModel->id, $childNode);
        }

        return [];
    }


    /**
     * 列表
     * @param int $pageNum
     * @param int $pageSize
     * @param int $status
     * @param int $workflowType
     * @return array
     */
    public function index(
        int $pageNum,
        int $pageSize,
        int $status,
        int $workflowType,
        string $name,
        string $templateNo
    ): array {
        $paginator = WorkflowV2TemplateModel::query()
                                            ->with('cruiseTemplateRel', 'updatedByUidRel')
                                            ->when($status != -1, function ($query) use ($status) {
                                                $query->where('status', $status);
                                            })
                                            ->when($workflowType, function ($query) use ($workflowType) {
                                                $query->where('workflowType', $workflowType);
                                            })
                                            ->when($name, function ($query) use ($name) {
                                                $query->where('name', 'like', "%{$name}%");
                                            })
                                            ->when($templateNo, function ($query) use ($templateNo) {
                                                $query->where('templateNo', $templateNo);
                                            })
                                            ->paginate($pageSize, ['*'], 'pageNum', $pageNum);

        return BaseService::pageLists($paginator, function ($item) {
            return [
                'id'                 => $item->id,
                'templateNo'         => $item->templateNo,
                'name'               => $item->name,
                'workflowType'       => $item->workflowType,
                'workflowTypeText'   => WorkflowV2Enum::WORKFLOW_TYPE_TEXT[$item->workflowType] ?? '-',
                'cruiseTemplateName' => (string)optional($item->cruiseTemplateRel)->name,
                'status'             => $item->status,
                'statusText'         => WorkflowV2TemplateModel::STATUS_TEXT[$item->status] ?? '-',
                'createdAt'          => $item->createdAt->toDateTimeString(),
                'updatedAt'          => $item->updatedAt->toDateTimeString(),
                'updatedByUid'       => $item->updatedByUid,
                'updatedByUsername'  => (string)optional($item->updatedByUidRel)->standardName,
            ];
        });
    }

    private Collection $nodesRel;

    public function detail(int $id): array
    {
        $template = WorkflowV2TemplateModel::query()->with('nodesRel')->find($id);
        if (!$template) {
            BaseService::throwErr('不存在的模板id，或已删除');
        }

        $this->nodesRel = $template->nodesRel->keyBy('id');

        return [
            'id'            => $template->id,
            'name'          => $template->name,
            'workflowType'  => $template->workflowType,
            'workflowType2' => $template->workflowType2,
            'sort'          => $template->sort,
            'nodeConfig'    => $this->recursionEncodeChildNode($template->nodesRel->first(), 0),
        ];
    }

    private array $nextNodesBind = [];

    /**
     * 递归生成childNode
     * @param WorkflowV2TemplateNodeModel $node
     * @return array
     */
    private function recursionEncodeChildNode(WorkflowV2TemplateNodeModel $node, int $prevId): array
    {
        // 保证if子节点，不会直接生成父节点的childNode
//        if (!isset($this->nextNodes[$node->nextId])) {
//            $this->nextNodes[$node->nextId] = 0;
//        }
//        $this->nextNodes[$node->nextId]++;
//
//        if (isset($this->nextNodes[$node->nextId]) && $this->nextNodes[$node->nextId] > 1) {
//            return [];
//        }
        if (!isset($this->nextNodesBind[$node->nextId])) {
            $this->nextNodesBind[$node->nextId] = $node->id;
        }

        if (isset($this->nextNodesBind[$node->id]) && $this->nextNodesBind[$node->id] != $prevId) {
            return [];
        }

        $childNode = [
            'nodeKey'          => $node->id,
            'nodeName'         => $node->name,
            'nodeType'         => $node->nodeType,
            'handlerType'      => $node->handlerType,
            'handlerUids'      => json_decode($node->handlerUids, true) ?? [],
            'businessType'     => $node->businessType,
            'cruiseTemplateId' => $node->cruiseTemplateId,
            'conditionNodes'   => [],
            'ccInfo'           => json_decode($node->ccInfo, true),
        ];

        // 有分支结构
        if ($node->nodeType == WorkflowV2Enum::NODE_TYPE_IF_MAIN) {
            $conditionNodes = WorkflowV2TemplateNodeModel::query()->where('pId', $node->id)->get();
            foreach ($conditionNodes as $conditionNode) {
                $childNode['conditionNodes'][] = array_filter([
                    'nodeKey'          => $conditionNode->id,
                    'nodeName'         => $conditionNode->name,
                    'nodeType'         => $conditionNode->nodeType,
                    'conditionList'    => json_decode($conditionNode->condition, true) ?? [], // 条件
                    'childNode'        => $this->recursionEncodeChildNode($this->nodesRel[$conditionNode->nextId], $conditionNode->id),
                ]);
            }
        }

        if ($node->nextId) {
            $childNode['childNode'] = $this->recursionEncodeChildNode($this->nodesRel[$node->nextId], $node->id);
        }

        return array_filter($childNode);
    }


    /**
     * 删除
     * @param int $id
     * @return void
     */
    public function delete(int $id, bool $softDeleted = true, bool $deleteWorkflowTemplate = true): void
    {
        $template = WorkflowV2TemplateModel::query()->find($id);
        if (!$template) {
            BaseService::throwErr('不存在的模板id，或已删除');
        }

        if ($softDeleted) {

            // 节点相关
            WorkflowV2TemplateNodeModel::query()->where('workflowTemplateId', $id)->update(['isDeleted' => 1]);
            if ($deleteWorkflowTemplate) {
                WorkflowV2TemplateModel::query()->where('id', $id)->update(['isDeleted' => 1]);
            }

        } else {

            // 节点相关
            WorkflowV2TemplateNodeModel::query()->where('workflowTemplateId', $id)->delete();
            if ($deleteWorkflowTemplate) {
                WorkflowV2TemplateModel::query()->where('id', $id)->delete();
            }
        }

        // 审计日志
        $content = vsprintf("审批流模板【删除】\n\n id:%s name:%s \n\n 操作人:%s-%s", [
            $template->id,
            $template->name,
            $this->currentUserName,
            $this->currentUserId
        ]);
        BuildFs::newRobot(SendFs::ROBOT_AUDIT_LOG)->setTitleContent("审批流v2 - 审计消息", $content)->send();
    }

    // 上下架
    public function onOff(int $id, int $status)
    {
        $template = WorkflowV2TemplateModel::query()->find($id);
        if (!$template) {
            BaseService::throwErr('不存在的模板id，或已删除');
        }

        $template->status = $status;
        $template->save();

        $statusText = WorkflowV2TemplateModel::STATUS_TEXT[$status] ?? '-';

        // 审计日志
        $content = vsprintf("审批流模板【{$statusText}】\n\n id:%s name:%s \n\n操作人:%s-%s", [
            $template->id,
            $template->name,
            $this->currentUserName,
            $this->currentUserId
        ]);
        BuildFs::newRobot(SendFs::ROBOT_AUDIT_LOG)->setTitleContent("审批流v2 - 审计消息", $content)->send();
    }
}
